#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import shutil
import subprocess
import platform
from datetime import datetime

# 确保中文显示正常
import matplotlib
matplotlib.use('Agg')  # 使用非交互式后端

# 打包配置
APP_NAME = "MBTI 16人格测试"
MAIN_SCRIPT = "main.py"
OUTPUT_DIR = "dist"
ICON_FILE = None  # 如果有图标文件，可以设置为图标路径

# 检查系统类型
if platform.system() != 'Windows':
    print("此打包脚本仅支持Windows系统！")
    sys.exit(1)

# 检查是否安装了PyInstaller
try:
    import PyInstaller
    print(f"已安装PyInstaller，版本: {PyInstaller.__version__}")
except ImportError:
    print("未安装PyInstaller，正在尝试安装...")
    try:
        subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"])
        print("PyInstaller安装成功！")
    except Exception as e:
        print(f"PyInstaller安装失败: {e}")
        print("请手动安装PyInstaller后再运行此脚本：pip install pyinstaller")
        sys.exit(1)

# 清理之前的构建文件
def clean_build_files():
    """清理之前的构建文件"""
    print("正在清理之前的构建文件...")
    
    # 清理dist目录
    if os.path.exists(OUTPUT_DIR):
        try:
            shutil.rmtree(OUTPUT_DIR)
            print(f"已清理目录: {OUTPUT_DIR}")
        except Exception as e:
            print(f"清理{OUTPUT_DIR}失败: {e}")
    
    # 清理build目录
    if os.path.exists("build"):
        try:
            shutil.rmtree("build")
            print("已清理目录: build")
        except Exception as e:
            print(f"清理build失败: {e}")
    
    # 清理.spec文件
    for file in os.listdir('.'):
        if file.endswith('.spec'):
            try:
                os.remove(file)
                print(f"已清理文件: {file}")
            except Exception as e:
                print(f"清理{file}失败: {e}")

# 创建打包命令
def create_build_command():
    """创建PyInstaller打包命令"""
    command = [
        sys.executable,
        "-m", "PyInstaller",
        "--name", APP_NAME,
        "--onefile",  # 打包为单个文件
        "--windowed",  # 不显示控制台窗口
        "--clean",  # 清理缓存和临时文件
        "--add-data", f"{os.path.abspath('requirements.txt')};.",  # 添加依赖文件
    ]
    
    # 如果有图标文件，添加图标参数
    if ICON_FILE and os.path.exists(ICON_FILE):
        command.extend(["--icon", ICON_FILE])
    
    # 添加主脚本
    command.append(MAIN_SCRIPT)
    
    return command

# 执行打包
def run_build():
    """执行打包操作"""
    # 清理之前的构建文件
    clean_build_files()
    
    # 创建打包命令
    build_command = create_build_command()
    print(f"执行打包命令: {' '.join(build_command)}")
    
    try:
        # 执行打包命令
        subprocess.check_call(build_command)
        print("\n打包成功！")
        
        # 验证打包结果
        dist_path = os.path.join(OUTPUT_DIR, f"{APP_NAME}.exe")
        if os.path.exists(dist_path):
            print(f"可执行文件已生成: {dist_path}")
            return True
        else:
            print(f"打包后的文件不存在: {dist_path}")
            return False
            
    except Exception as e:
        print(f"打包失败: {e}")
        return False

# 创建安装程序配置
def create_nsis_script():
    """创建NSIS安装脚本"""
    nsis_script = f'''
; MBTI 16人格测试软件安装脚本
; 此脚本需要使用NSIS (Nullsoft Scriptable Install System) 编译

Name "{APP_NAME}"
OutFile "{APP_NAME}_安装程序.exe"
InstallDir $PROGRAMFILES\\{APP_NAME}

; 定义安装程序界面
Page custom WelcomePage
Page components
Page directory
Page instfiles

; 定义卸载程序界面
UninstPage uninstConfirm
UninstPage instfiles

; 定义安装程序属性
ShowInstDetails show
ShowUnInstDetails show

; 定义安装程序图标
; 如果有图标文件，可以取消下面一行的注释并设置图标路径
; Icon "icon.ico"

Section "主程序" SecMain
    SetOutPath $INSTDIR
    File "dist\\{APP_NAME}.exe"
    File "requirements.txt"
    File "README.md"
    
    ; 创建开始菜单快捷方式
    CreateDirectory $SMPROGRAMS\\{APP_NAME}
    CreateShortCut $SMPROGRAMS\\{APP_NAME}\\{APP_NAME}.lnk $INSTDIR\\{APP_NAME}.exe
    
    ; 创建桌面快捷方式
    CreateShortCut $DESKTOP\\{APP_NAME}.lnk $INSTDIR\\{APP_NAME}.exe
    
    ; 写入卸载注册表信息
    WriteUninstaller $INSTDIR\\uninstall.exe
    WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{APP_NAME}" "DisplayName" "{APP_NAME}"
    WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{APP_NAME}" "UninstallString" "$INSTDIR\\uninstall.exe"
    WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{APP_NAME}" "DisplayIcon" "$INSTDIR\\{APP_NAME}.exe"
    WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{APP_NAME}" "Publisher" "MBTI人格测试团队"
SectionEnd

Section "卸载程序"
    ; 删除开始菜单快捷方式
    Delete $SMPROGRAMS\\{APP_NAME}\\{APP_NAME}.lnk
    RMDir $SMPROGRAMS\\{APP_NAME}
    
    ; 删除桌面快捷方式
    Delete $DESKTOP\\{APP_NAME}.lnk
    
    ; 删除程序文件
    Delete $INSTDIR\\{APP_NAME}.exe
    Delete $INSTDIR\\requirements.txt
    Delete $INSTDIR\\README.md
    Delete $INSTDIR\\uninstall.exe
    
    ; 删除程序目录
    RMDir $INSTDIR
    
    ; 删除注册表信息
    DeleteRegKey HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{APP_NAME}"
SectionEnd

; 自定义欢迎页面
Function WelcomePage
    !insertmacro MUI_HEADER_TEXT "欢迎使用{APP_NAME}" "感谢您选择{APP_NAME}"
    
    nsDialogs::Create 1018
    Pop $0
    
    ${If} $0 == error
        Abort
    ${EndIf}
    
    ; 添加欢迎文字
    nsDialogs::CreateControl STATIC "${NSD_CENTER}|${NSD_VCENTER}|AUTORESIZE" $0 0 40 100% 60 "欢迎使用${APP_NAME}安装程序！\r\n\r\n本软件帮助您了解自己的性格特点、优势和潜在发展方向。\r\n\r\n点击'下一步'继续安装。"
    
    nsDialogs::Show
FunctionEnd
    '''
    
    # 保存NSIS脚本到文件
    with open(f"{APP_NAME}_安装脚本.nsi", "w", encoding="utf-8") as f:
        f.write(nsis_script)
    
    print(f"已生成NSIS安装脚本: {APP_NAME}_安装脚本.nsi")
    print("\n注意：要生成安装程序，您需要安装NSIS (Nullsoft Scriptable Install System)，然后使用NSIS编译此脚本。")
    print("NSIS官方网站: https://nsis.sourceforge.io/")

# 主函数
def main():
    print(f"开始打包{APP_NAME}...")
    print(f"当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print(f"Python版本: {platform.python_version()}")
    print(f"操作系统: {platform.system()} {platform.release()}")
    print("="*60)
    
    # 执行打包
    build_success = run_build()
    
    if build_success:
        print("="*60)
        print("打包完成！")
        print(f"可执行文件路径: {os.path.abspath(os.path.join(OUTPUT_DIR, f'{APP_NAME}.exe'))}")
        
        # 询问是否生成NSIS安装脚本
        create_installer = input("\n是否生成NSIS安装脚本？(y/n): ").strip().lower()
        if create_installer == 'y':
            create_nsis_script()
            
        print("\n打包总结:")
        print(f"1. 主程序已打包为单文件可执行程序")
        print(f"2. 程序支持Windows 10及以上版本")
        print(f"3. 程序会在用户的AppData目录下存储数据")
        print(f"4. 如需创建安装程序，请使用NSIS编译生成的.nsi脚本")
        
    else:
        print("\n打包失败，请检查错误信息并重试。")
        print("可能的解决方案：")
        print("1. 确保所有依赖包已正确安装: pip install -r requirements.txt")
        print("2. 确保main.py文件存在且没有语法错误")
        print("3. 如果有图标文件，请确保路径正确")

if __name__ == "__main__":
    main()